package com.direct.ratelimit.threshold;

import java.util.ArrayList;
import java.util.Collection;

import com.direct.ratelimit.RateLimitRequest;
import com.direct.ratelimit.action.Action;
import com.direct.ratelimit.action.ActionFactory;
import com.direct.ratelimit.limit.DefaultLimitService;
import com.direct.ratelimit.limit.Limit;
import com.direct.ratelimit.limit.LimitService;

public class DefaultThresholdService implements ThresholdService {

	private ThresholdConfigDAO threshConfigDAO = new CSVFileThresholdConfigDAO();
	private ActionFactory actionFactory;

	private LimitService limitService = new DefaultLimitService();

	@Override
	public Collection<Threshold> getThresholds(RateLimitRequest rateLimitRequest) {

		Collection<Limit> limits = limitService.getLimits(rateLimitRequest);

		Collection<ThresholdConfig> thresholdConfigs = threshConfigDAO.getThresholdConfigs(limits);
		Collection<Threshold> thresholds = new ArrayList<Threshold>(thresholdConfigs.size());

		// FIXME any bad threshold will cause everythign to fail. do we want
		// that type of behavior?
		for (ThresholdConfig thresholdConfig : thresholdConfigs) {
			Action action = actionFactory.getAction(thresholdConfig.getActionId());
			if (action == null) {
				throw new IllegalStateException("something bad happened action should not be null: " + thresholdConfig.toString());
			}

			// these list are so small that this is ok
			Limit limit = null;
			for (Limit _limit : limits) {
				if (_limit.getId().equals(thresholdConfig.getLimitId())) {
					limit = _limit;
					break;
				}
			}
			if (limit == null) {
				throw new IllegalStateException("something bad happened limit should not be null: " + thresholdConfig.toString());
			}
			// if we made it here everything is good
			thresholds.add(new Threshold(thresholdConfig.getPercentage(), limit, action));
		}

		return thresholds;
	}

	@Override
	public boolean isThresholdExceeded(Threshold threshold, long value) {
		return value >= (threshold.getLimit().getRequestLimit() * (threshold.getPercentage() / 100));
	}

	public void setActionFactory(ActionFactory actionFactory) {
		this.actionFactory = actionFactory;
	}

	public void setThreshConfigDAO(ThresholdConfigDAO threshConfigDAO) {
		this.threshConfigDAO = threshConfigDAO;
	}

	public void setLimitServicef(LimitService limitService) {
		this.limitService = limitService;
	}

}
